<?php
/******************************************************
v4 - Management Framework
Copyright (C) 2008  Gary Taylor, gMerc Incorporation
http://www.gmerc.com/v4/

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

gary@gmerc.com
******************************************************/
class captcha {
  function captcha() {
    global $masterclass;
    
    $masterclass->site['captcha_flag']='1';
  return;
  }
  
  function captcha_image_overlaylink($captcha_width=100,$captcha_height=200) {
    global $masterclass;
    
    $validatelink='captcha_overlay_auth(document.getElementById(\'captcha_val\').value,document.getElementById(\'captchaid\').value);';
    $ret='';
    $ret.='<div>';
    $ret.='CAPTCHA SECURITY CODE<br>';
    $ret.='<img ';
    $ret.=' src="'.$masterclass->mainconfig['dir'].'captcha_image.php?captchaid='.$masterclass->site['captcha_id'].'" ';
    $ret.=' alt="CAPTCHA" ';
    if ($captcha_width!='') { $ret.=' width="'.$captcha_width.'" '; }
    if ($captcha_height!='') { $ret.=' height="'.$captcha_height.'" '; }
    $ret.='><br>';
    $ret.='<input type="text" name="captcha_val" id="captcha_val" size="6" maxlength="6" OnKeyPress="if (event.keyCode == 13) { '.$validatelink.' }"><br>';
    $ret.='<input type="button" OnClick="'.$validatelink.'" Value=" VERIFY HUMAN ">&nbsp;<input type="button" OnClick="captcha_overlay();" Value=" CANCEL ">';
    $ret.='</div>';
  
  return $ret;
  }
  function captcha_image_link($captcha_width=100,$captcha_height=200) {
    global $masterclass;
    
    $ret='';
    $ret.='<div>';
    $ret.='CAPTCHA SECURITY CODE<br>';
    $ret.='<img ';
    $ret.=' src="'.$masterclass->mainconfig['dir'].'captcha_image.php?captchaid='.$masterclass->site['captcha_id'].'" ';
    $ret.=' alt="CAPTCHA" ';
    if ($captcha_width!='') { $ret.=' width="'.$captcha_width.'" '; }
    if ($captcha_height!='') { $ret.=' height="'.$captcha_height.'" '; }
    $ret.='>';
    $ret.='</div>';
  
  return $ret;
  }
  function captcha_validate_word($str='',$id='') {
    global $masterclass;
    
    if ($str=='' || $id=='') { return '0'; }
    if (!isset($_SESSION['captcha_val_'.$id])) { return '0'; }
    if ($_SESSION['captcha_val_'.$id]=='') { return '0'; }
    
    if (strtolower($str)==strtolower($_SESSION['captcha_val_'.$id])) { 
      return '1';
    }
    unset($_SESSION['captcha_val_'.$id]);
  
  return '0';
  }
  function captcha_validate_ajax($str='',$id='',$actionlist='') {
    global $masterclass;
    $arrret=array();
    
    if ($str=='' && $id=='') { $masterclass->site['captcha_overlay_auth_vars']['captcha_message']="COULD NOT VALIDATE, TRY AGAIN\n\nNOT SAVED";return false; }
    if (strtolower($_SESSION['captcha_val_'.$id])==strtolower($str)) {
      $masterclass->site['captcha_overlay_auth_vars']['captcha_message']='';
      if ($actionlist!='') { $masterclass->site['captcha_overlay_auth_vars']['run_command']=$actionlist; }
      $_SESSION['captcha_auth_'.$id]=$_SESSION['captcha_val_'.$id];
      return;
    } else {
      $masterclass->site['captcha_overlay_auth_vars']['captcha_message']="COULD NOT VALIDATE, TRY AGAIN\n\nNOT SAVED";
    }
  return false;
  }

  function captcha_generate_word() {
    global $masterclass;
    
    $str='';
    // some easy-to-confuse letters taken out C/G I/l Q/O h/b 
    if (!isset($masterclass->site['hkcaptcha_charactors']) || $masterclass->site['hkcaptcha_charactors']=='') {
      $masterclass->site['hkcaptcha_charactors'] = "ABDEFHJKMNPQRTUVWVYZ24679";
    }
    if (!isset($masterclass->site['hkcaptcha_charactorslength']) || $masterclass->site['hkcaptcha_charactorslength']=='') {
      $masterclass->site['hkcaptcha_charactorslength'] = 6;
    }
    for ($i = 0; $i < $masterclass->site['hkcaptcha_charactorslength']; ++$i) {
      $str .= substr($masterclass->site['hkcaptcha_charactors'], rand(0,strlen($masterclass->site['hkcaptcha_charactors'])-1), 1);
    }
 
   return $str;
  }
  function captcha_generate_image($str,$captcha_width=200,$captcha_height=100) {
    global $masterclass;
    
    $this->hkcaptcha_font = $masterclass->site['server_path']."include/VeraSe.ttf";
    $this->hkcaptcha_imgwid = $captcha_width;
    $this->hkcaptcha_imghgt = $captcha_height;
    
    $image = $this->hkcaptcha_warped_text_image($captcha_width, $captcha_height, $str);
  
  return $image;
  }
  function captcha_display_image($image) {
    header("Content-type: image/png");
    imagepng($image);
    imagedestroy ($image);
  }
  
  
/***************************************

 Han-Kwang Nienhuys' PHP captcha
 Copyright June 2007
 Home page: http://www.lagom.nl/linux/hkcaptcha/
 
 This file may be distributed, modified, and used freely as long as
 the above attribution and this copyright message is preserved.
 
 Yet another captcha implementation in PHP.  This one is written with
 the current state of captcha-defeating research in mind. Apart from a
 letter distortion that is more advanced than just rotating the
 letters, the clutter is designed to make segmentation of the image
 into separate letter glyphs hard to do automatically.

 The 5-letter code is stored into the PHP session variable
 $_SESSION['captcha_string']; see the examples example.html and verify.php.
 
***************************************/
  function hkcaptcha_config() {
    global $masterclass;
    
    if (!isset($this->hkcaptcha_font)) $this->hkcaptcha_font = $masterclass->site['hkcaptcha_font'];
    if (!isset($this->hkcaptcha_perturbation)) $this->hkcaptcha_perturbation = $masterclass->site['hkcaptcha_perturbation']; // bigger numbers give more distortion; 1 is standard
    if (!isset($this->hkcaptcha_imgwid)) $this->hkcaptcha_imgwid = $masterclass->site['hkcaptcha_imgwid']; // image width, pixels
    if (!isset($this->hkcaptcha_imghgt)) $this->hkcaptcha_imghgt = $masterclass->site['hkcaptcha_imghgt']; // image height, pixels
    if (!isset($this->hkcaptcha_numcirc)) $this->hkcaptcha_numcirc = $masterclass->site['hkcaptcha_numcirc']; // number of wobbly circles
    if (!isset($this->hkcaptcha_numlines)) $this->hkcaptcha_numlines = $masterclass->site['hkcaptcha_numlines']; // number of lines
    if (!isset($this->hkcaptcha_ncols)) $this->hkcaptcha_ncols = $masterclass->site['hkcaptcha_ncols']; // foreground or background cols
    
    if (!isset($this->hkcaptcha_font)) $this->hkcaptcha_font = $masterclass->site['server_path']."include/VeraSe.ttf";
    if (!isset($this->hkcaptcha_perturbation)) $this->hkcaptcha_perturbation = 1.0; // bigger numbers give more distortion; 1 is standard
    if (!isset($this->hkcaptcha_imgwid)) $this->hkcaptcha_imgwid = 200; // image width, pixels
    if (!isset($this->hkcaptcha_imghgt)) $this->hkcaptcha_imghgt = 100; // image height, pixels
    if (!isset($this->hkcaptcha_numcirc)) $this->hkcaptcha_numcirc = 1; // number of wobbly circles
    if (!isset($this->hkcaptcha_numlines)) $this->hkcaptcha_numlines = 1; // number of lines
    if (!isset($this->hkcaptcha_ncols)) $this->hkcaptcha_ncols = 20; // foreground or background cols
  }
  function hkcaptcha_frand() {
    return 0.0001*rand(0,9999);
  }

  // wiggly random line centered at specified coordinates
  function hkcaptcha_randomline($img, $col, $x, $y) {
    $theta = ($this->hkcaptcha_frand()-0.5)*M_PI*0.7;

    $len = rand($this->hkcaptcha_imgwid*0.4,$this->hkcaptcha_imgwid*0.7);
    $lwid = rand(0,2);

    $k = $this->hkcaptcha_frand()*0.6+0.2; $k = $k*$k*0.5;
    $phi = $this->hkcaptcha_frand()*6.28;
    $step = 0.5;
    $dx = $step*cos($theta);
    $dy = $step*sin($theta);
    $n = $len/$step;
    $amp = 1.5*$this->hkcaptcha_frand()/($k+5.0/$len);
    $x0 = $x - 0.5*$len*cos($theta);
    $y0 = $y - 0.5*$len*sin($theta);

    $ldx = round(-$dy*$lwid);
    $ldy = round($dx*$lwid);
    for ($i = 0; $i < $n; ++$i) {
      $x = $x0+$i*$dx + $amp*$dy*sin($k*$i*$step+$phi);
      $y = $y0+$i*$dy - $amp*$dx*sin($k*$i*$step+$phi);
      imagefilledrectangle($img, $x, $y, $x+$lwid, $y+$lwid, $col);
    }
  }

  // amp = amplitude (<1), num=numwobb (<1)
  function hkcaptcha_imagewobblecircle($img, $xc, $yc, $r, $wid, $amp, $num, $col) {
    $dphi = 1;
    if ($r > 0)
      $dphi = 1/(6.28*$r);
    $woffs = rand(0,100)*0.06283;
    for ($phi = 0; $phi < 6.3; $phi += $dphi) {
      $r1 = $r * (1-$amp*(0.5+0.5*sin($phi*$num+$woffs)));
      $x = $xc + $r1*cos($phi);
      $y = $yc + $r1*sin($phi);
      imagefilledrectangle($img, $x, $y, $x+$wid, $y+$wid, $col);
    }
  }

  // make a distorted copy from $tmpimg to $img. $wid,$height apply to $img,
  // $tmpimg is a factor $iscale bigger.
  function hkcaptcha_distorted_copy($tmpimg, $img, $width, $height, $iscale) {
    $numpoles = 3;

    // make an array of poles AKA attractor points
    for ($i = 0; $i < $numpoles; ++$i) {
      do {
        $px[$i] = rand(0, $width);
      } while ($px[$i] >= $width*0.3 && $px[$i] <= $width*0.7);
      do {
        $py[$i] = rand(0, $height);
      } while ($py[$i] >= $height*0.3 && $py[$i] <= $height*0.7);
      $rad[$i] = rand($width*0.4, $width*0.8);
      $tmp = -$this->hkcaptcha_frand()*0.15-0.15;
      $amp[$i] = $this->hkcaptcha_perturbation * $tmp;
    }

    // get img properties bgcolor
    $bgcol = imagecolorat($tmpimg, 1, 1);
    $width2 = $iscale*$width;
    $height2 = $iscale*$height;
  
    // loop over $img pixels, take pixels from $tmpimg with distortion field
    for ($ix = 0; $ix < $width; ++$ix)
      for ($iy = 0; $iy < $height; ++$iy) {
        $x = $ix;
        $y = $iy;
        for ($i = 0; $i < $numpoles; ++$i) {
	      $dx = $ix - $px[$i];
	      $dy = $iy - $py[$i];
	      if ($dx == 0 && $dy == 0)
	        continue;
	      $r = sqrt($dx*$dx + $dy*$dy);
	      if ($r > $rad[$i])
	        continue;
  	      $rscale = $amp[$i] * sin(3.14*$r/$rad[$i]);
  	      $x += $dx*$rscale;
	      $y += $dy*$rscale;
        }
        $c = $bgcol;
        $x *= $iscale;
        $y *= $iscale;
        if ($x >= 0 && $x < $width2 && $y >= 0 && $y < $height2)
	      $c = imagecolorat($tmpimg, $x, $y);
        imagesetpixel($img, $ix, $iy, $c);
      }
  }

  // add grid for debugging purposes
  function hkcaptcha_addgrid($tmpimg, $width2, $height2, $iscale, $color) {
    $lwid = floor($iscale*3/2);
    imagesetthickness($tmpimg, $lwid);
    for ($x = 4; $x < $width2-$lwid; $x+=$lwid*2)
      imageline($tmpimg, $x, 0, $x, $height2-1, $color);
    for ($y = 4; $y < $height2-$lwid; $y+=$lwid*2)
      imageline($tmpimg, 0, $y, $width2-1, $y, $color);
  }


  function hkcaptcha_warped_text_image($width, $height, $string) {
    $this->hkcaptcha_config();
    // internal variablesinternal scale factor for antialias
    $iscale = 3;

    // initialize temporary image
    $width2 = $iscale*$width;
    $height2 = $iscale*$height;
    $tmpimg = imagecreate($width2, $height2);
    $bgColor = imagecolorallocatealpha ($tmpimg, 192, 192, 192, 100);
    $col = imagecolorallocate($tmpimg, 0, 0, 0);

    // init final image
    $img = imagecreate($width, $height);
    imagepalettecopy($img, $tmpimg);    
    imagecopy($img, $tmpimg, 0,0 ,0,0, $width, $height);
  
    // put straight text into $tmpimage
    $fsize = $height2*0.25;
    $bb = imageftbbox($fsize, 0, $this->hkcaptcha_font, $string);
    $tx = $bb[4]-$bb[0];
    $ty = $bb[5]-$bb[1];
    $x = floor($width2/2 - $tx/2 - $bb[0]);
    $y = round($height2/2 - $ty/2 - $bb[1]);
    imagettftext($tmpimg, $fsize, 0, $x, $y, -$col, $this->hkcaptcha_font, $string);

    // $this->hkcaptcha_addgrid($tmpimg, $width2, $height2, $iscale, $col); // debug

    // warp text from $tmpimg into $img
    $this->hkcaptcha_distorted_copy($tmpimg, $img, $width, $height, $iscale);

    // add wobbly circles (spaced)

    for ($i = 0; $i < $this->hkcaptcha_numcirc; ++$i) {
      $x = $width * (1+$i) / ($this->hkcaptcha_numcirc+1);
      $x += (0.5-$this->hkcaptcha_frand())*$width/$this->hkcaptcha_numcirc;
      $y = rand($height*0.1, $height*0.9);
      $r = $this->hkcaptcha_frand();
      $r = ($r*$r+0.2)*$height*0.2;
      $lwid = rand(0,2);
      $wobnum = rand(1,4);
      $wobamp = $this->hkcaptcha_frand()*$height*0.01/($wobnum+1);
      $this->hkcaptcha_imagewobblecircle($img, $x, $y, $r, $lwid, $wobamp, $wobnum, $col);
    }
  
    // add wiggly lines
    for ($i = 0; $i < $this->hkcaptcha_numlines; ++$i) {
      $x = $width * (1+$i) / ($this->hkcaptcha_numlines+1);
      $x += (0.5-$this->hkcaptcha_frand())*$width/$this->hkcaptcha_numlines;
      $y = rand($height*0.1, $height*0.9);
      $this->hkcaptcha_randomline($img, $col, $x, $y);
    }

    return $img;
  }
 
}
?>